home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / mac / macmenus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  49.3 KB  |  2,046 lines  |  [TEXT/R*ch]

  1. /* Menus and commands for the Mac interface to Xconq.
  2.    Copyright (C) 1992, 1993, 1994, 1995, 1996 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "conq.h"
  10. #include "print.h"
  11. #include "macconq.h"
  12. extern void enable_command(void);
  13. extern TEHandle command_text;
  14. extern TEHandle run_length_text;
  15.  
  16. void
  17. query_position_modally(int mode)
  18.  
  19. {
  20.     if (map_modal == NO_MODAL) {
  21.         map_modal = mode;
  22.     } else {
  23.         beep();
  24.     }
  25. }
  26.  
  27. void
  28. set_position_modally()
  29. {
  30.     modal_map = map_from_window(FrontWindow());
  31.     GetMouse(&modal_point);
  32.     position_set_modally = TRUE;
  33. }
  34.  
  35. #undef DEF_CMD
  36. #define DEF_CMD(letter,name,args,FN,help) extern void FN(void);
  37.  
  38. #include "cmd.def"
  39.  
  40. #include "maccmd.def"
  41.  
  42. extern int do_one_give(Unit *unit);
  43. extern int do_one_take(Unit *unit);
  44. extern int do_one_return(Unit *unit);
  45. extern int do_one_detonate(Unit *unit);
  46. extern int do_one_repair(Unit *unit);
  47. extern int do_one_give_unit(Unit *unit);
  48. extern int do_one_detach(Unit *unit);
  49. extern int do_one_disband(Unit *unit);
  50.  
  51. extern int do_one_clear_plan(Unit *unit);
  52. extern int do_one_dir_move(Unit *unit);
  53. extern int do_one_dir_multiple_move(Unit *unit);
  54. extern int do_one_set_name(Unit *unit);
  55.  
  56. static void sanitize_for_menu(char *str, Str255 outstr);
  57.  
  58. static void resign_the_game(int forced);
  59.  
  60. static void te_cut(TEHandle hdl);
  61. static void te_copy(TEHandle hdl);
  62. static void te_paste(TEHandle hdl);
  63.  
  64. static void do_page_setup_mi(void);
  65. static void do_print_mi(void);
  66. static void do_select_all_mi(void);
  67. static void do_find_previous_mi(void);
  68. static void do_find_next_mi(void);
  69. static void do_find_location_mi(void);
  70. static void do_find_unit_by_name_mi(void);
  71. static void do_find_selected_mi(void);
  72. static void do_closeup_mi(void);
  73. static void do_move_mi(void);
  74. static void do_patrol_mi(void);
  75. static void do_wake_mi(void);
  76. static void do_sleep_mi(void);
  77. static void do_done_moving_mi(void);
  78. static void do_construction_mi(void);
  79. static void do_repair_mi(void);
  80. static void do_attack_mi(void);
  81. static void do_overrun_mi(void);
  82. static void do_fire_mi(void);
  83. static void do_fire_into_mi(void);
  84. static void do_take_mi(void);
  85. static void do_detonate_mi(void);
  86. static void do_give_unit_mi(int mi);
  87. static void do_disband_mi(void);
  88. static void moveonclick_mi(void);
  89. static void autoselect_mi(void);
  90.  
  91. static void adjust_menu_item(MenuHandle menu, int item, int value);
  92. extern void enable_commands_for_unit(MenuHandle menu, Unit *unit);
  93.  
  94. int forcedtoresign;
  95.  
  96. int modal_construction = FALSE;
  97.  
  98. WindowPtr window_behind_construction;
  99.  
  100. extern Feature *featurelist;
  101.  
  102. #ifdef THINK_C
  103. #include <profile.h>
  104. #endif
  105.  
  106. int Profile = FALSE;
  107.  
  108. #ifdef DESIGNERS
  109. #define side_may_select(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
  110.  
  111. #define valid_selection(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
  112.  
  113. #define menus_tweakable() ((!beforestart && !endofgame) || (gameinited && dside->designer))
  114. #else /* n DESIGNERS */
  115. #define side_may_select(unit) (in_play(unit) && ((unit)->side == dside))
  116.  
  117. #define valid_selection(unit) (in_play(unit) && ((unit)->side == dside))
  118.  
  119. #define menus_tweakable() ((!beforestart && !endofgame) || (gameinited))
  120. #endif /* DESIGNERS */
  121.  
  122. #define MAXWINDOWS 100
  123.  
  124. char *cursavename = NULL;
  125.  
  126. MenuHandle mapviewmenu = nil;
  127. MenuHandle listviewmenu = nil;
  128. MenuHandle closeupviewmenu = nil;
  129.  
  130. MenuHandle utypemenu = nil;
  131. MenuHandle ttypemenu = nil;
  132. MenuHandle mtypemenu = nil;
  133. MenuHandle sidemenu = nil;
  134. MenuHandle aitypemenu = nil;
  135.  
  136. MenuHandle featuremenu = nil;
  137. MenuHandle optterrmenu = nil;
  138.  
  139. WindowPtr *winmenuwins;
  140.  
  141. int numwindows;
  142.  
  143. Map *worldmap = NULL;
  144.  
  145. WindowPtr worldmapwin = nil;
  146.  
  147. /* Set up all the menus, at least in their basic form. */
  148.  
  149. void
  150. init_menus()
  151. {
  152.     int i;
  153.     Handle menubar;
  154.     MenuHandle menu;
  155.  
  156.     menubar = GetNewMBar(mbMain);
  157.     SetMenuBar(menubar);
  158.     /* Add the DAs etc as usual. */
  159.     menu = GetMHandle(mApple);
  160.     if (menu != nil)
  161.       AddResMenu(menu, 'DRVR');
  162.     /* Get the different versions of the view menu. */
  163.     mapviewmenu = GetMenu(mViewMap);
  164.     listviewmenu = GetMenu(mViewList);
  165.     closeupviewmenu = GetMenu(mViewCloseup);
  166.     /* Init submenus and popups. */
  167.     menu = GetMenu(mViewFontSizes);
  168.     if (menu != nil)
  169.       InsertMenu(menu, -1);
  170.     menu = GetMenu(mMagnifications);
  171.     if (menu != nil)
  172.       InsertMenu(menu, -1);
  173.     menu = GetMenu(mViewWeather);
  174.     if (menu != nil)
  175.       InsertMenu(menu, -1);
  176.     sidemenu = GetMenu(mSides);
  177.     if (sidemenu != nil)
  178.       InsertMenu(sidemenu, -1);
  179.     utypemenu = GetMenu(mUnitTypes);
  180.     if (utypemenu != nil)
  181.       InsertMenu(utypemenu, -1);
  182.     mtypemenu = GetMenu(mMaterialTypes);
  183.     if (mtypemenu != nil)
  184.       InsertMenu(mtypemenu, -1);
  185.     ttypemenu = GetMenu(mTerrainTypes);
  186.     if (ttypemenu != nil)
  187.       InsertMenu(ttypemenu, -1);
  188.     aitypemenu = GetMenu(mAITypes);
  189.     if (aitypemenu != nil)
  190.       InsertMenu(aitypemenu, -1);
  191.     featuremenu = GetMenu(mFeatures);
  192.     if (featuremenu != nil)
  193.       InsertMenu(featuremenu, -1);
  194.     optterrmenu = GetMenu(mOptTerrainTypes);
  195.     if (optterrmenu != nil)
  196.       InsertMenu(optterrmenu, -1);
  197.     menu = GetMenu(mViewAngles);
  198.     if (menu != nil)
  199.       InsertMenu(menu, -1);
  200.     /* Init the support for the Windows menu. */
  201.     winmenuwins = (WindowPtr *) xmalloc(MAXWINDOWS * sizeof(WindowPtr));
  202.     for (i = 0; i < MAXWINDOWS; ++i)
  203.       winmenuwins[i] = nil;
  204.     numwindows = 0;
  205.     /* Done fiddling with menus, draw them. */
  206.     DrawMenuBar();
  207. }
  208.  
  209. /* Add a menu item that can be used to go to the given window.  Set the window title
  210.    here too, ensures that the two match. */
  211.  
  212. void
  213. add_window_menu_item(char *name, WindowPtr win)
  214. {
  215.     MenuHandle menu;
  216.     Str255 tmpstr;
  217.  
  218.     if (numwindows < MAXWINDOWS) {
  219.         c2p(name, tmpstr);
  220.         SetWTitle(win, tmpstr);
  221.         winmenuwins[numwindows++] = win;
  222.         menu = GetMHandle(mWindows);
  223.         if (menu != nil)
  224.           AppendMenu(menu, tmpstr);
  225.     }
  226. }
  227.  
  228. /* Remove the menu item that can be used to select a given window. */
  229.  
  230. void
  231. remove_window_menu_item(WindowPtr win)
  232. {
  233.     int i, found = FALSE, next = 0;
  234.     Str255 tmpstr;
  235.     MenuHandle menu;
  236.  
  237.     /* Search for the window and remove it from the array of windows
  238.        that have menu items. */
  239.     for (i = 0; i < numwindows; ++i) {
  240.         if (!found && winmenuwins[i] == win) {
  241.             found = TRUE;
  242.         }
  243.         if (found && i < numwindows - 1) {
  244.             /* Shift the other windows down. */
  245.             winmenuwins[i] = winmenuwins[i + 1];
  246.         }
  247.     }
  248.     /* This routine gets called for all windows, so get out of here
  249.        if this window is not one of those in the menu. */
  250.     if (!found)
  251.       return;
  252.     --numwindows;
  253.     /* Trash the existing window menu. */
  254.     menu = GetMHandle(mWindows);
  255.     if (menu != nil) {
  256.         DeleteMenu(mWindows);
  257.         ReleaseResource((Handle) menu);
  258.     }
  259.     /* Build a new version starting with the resource. */
  260.     menu = GetMenu(mWindows);
  261.     if (menu != nil) {
  262.         for (i = 0; i < numwindows; ++i) {
  263.             GetWTitle(winmenuwins[i], tmpstr);
  264.             AppendMenu(menu, tmpstr);
  265.         }
  266.         /* Glue a view menu on after the windows menu. */
  267.         if (GetMHandle(mViewMap) != nil)
  268.           next = mViewMap;
  269.         if (GetMHandle(mViewList) != nil)
  270.           next = mViewList;
  271.         InsertMenu(menu, next);
  272.     }
  273.     DrawMenuBar();
  274. }
  275.  
  276. /* Fill up the side menu. */
  277.  
  278. void
  279. build_side_menu()
  280. {
  281.     char *title;
  282.     Side *side2;
  283.     Str255 tmpstr;
  284.  
  285.     if (sidemenu != nil && CountMItems(sidemenu) < 1) {
  286.         for_all_sides(side2) {
  287.             title = shortest_side_title(side2, spbuf);
  288.             sanitize_for_menu(title, tmpstr);
  289.             AppendMenu(sidemenu, tmpstr);
  290.             EnableItem(sidemenu, side_number(side2));
  291.         }
  292.         if (1 /* independent units possible in this game */) {
  293.             AppendMenu(sidemenu, "\pindependent");
  294.         }
  295.     }
  296. }
  297.  
  298. void
  299. update_side_menu(Side *side2)
  300. {
  301.     char *title;
  302.     Str255 tmpstr;
  303.  
  304.     title = shortest_side_title(side2, spbuf);
  305.     sanitize_for_menu(title, tmpstr);
  306.     SetMenuItemText(sidemenu, side_number(side2), tmpstr);
  307. }
  308.  
  309. void
  310. build_unit_type_menu()
  311. {
  312.     int u;
  313.     Str255 tmpstr;
  314.  
  315.     if (utypemenu != nil && CountMItems(utypemenu) < 1) {
  316.         for_all_unit_types(u) {
  317.             sanitize_for_menu(u_type_name(u), tmpstr);
  318.             AppendMenu(utypemenu, tmpstr);
  319.             EnableItem(utypemenu, u + 1);
  320.         }
  321.     }
  322. }
  323.  
  324. void
  325. build_material_type_menu()
  326. {
  327.     int m;
  328.     Str255 tmpstr;
  329.  
  330.     if (mtypemenu != nil && CountMItems(mtypemenu) < 1 && nummtypes > 0) {
  331.         for_all_material_types(m) {
  332.             sanitize_for_menu(m_type_name(m), tmpstr);
  333.             AppendMenu(mtypemenu, tmpstr);
  334.             EnableItem(mtypemenu, m + 1);
  335.         }
  336.     }
  337. }
  338.  
  339. void
  340. build_terrain_type_menu()
  341. {
  342.     int t;
  343.     Str255 tmpstr;
  344.  
  345.     if (ttypemenu != nil && CountMItems(ttypemenu) < 1) {
  346.         for_all_terrain_types(t) {
  347.             sanitize_for_menu(t_type_name(t), tmpstr);
  348.             AppendMenu(ttypemenu, tmpstr);
  349.             EnableItem(ttypemenu, t);
  350.         }
  351.     }
  352. }
  353.  
  354. void
  355. build_ai_type_menu()
  356. {
  357.     if (aitypemenu != nil && CountMItems(aitypemenu) < 1) {
  358.         AppendMenu(aitypemenu, "\pNone");
  359.         EnableItem(aitypemenu, 1);
  360.         AppendMenu(aitypemenu, "\pMplayer");
  361.         EnableItem(aitypemenu, 2);
  362.     }
  363. }
  364.  
  365. void
  366. build_feature_menu()
  367. {
  368.     int i = 1;
  369.     char *name;
  370.     Str255 tmpstr;
  371.     Feature *feature;
  372.     MenuHandle oldmenu, newmenu = nil;
  373.  
  374.     if (featuremenu != nil) {
  375.         if (CountMItems(featuremenu) >= 1) {
  376.             /* Trash the existing feature menu. */
  377.             oldmenu = GetMHandle(mFeatures);
  378.             if (oldmenu != nil) {
  379.                 DeleteMenu(mFeatures);
  380.                 ReleaseResource((Handle) oldmenu);
  381.                 /* Build a new version starting with the resource. */
  382.                 if ((newmenu = GetMenu(mFeatures)) != nil) {
  383.                     featuremenu = newmenu;
  384.                 }
  385.             }
  386.         }
  387.         AppendMenu(featuremenu, "\pNo Feature");
  388.         EnableItem(featuremenu, i++);
  389.         for (feature = featurelist; feature != NULL; feature = feature->next) {
  390.             name = feature_desc(feature, spbuf);
  391.             sanitize_for_menu(name, tmpstr);
  392.             AppendMenu(featuremenu, tmpstr);
  393.             EnableItem(featuremenu, i++);
  394.         }
  395.         if (newmenu != nil) {
  396.             InsertMenu(featuremenu, -1);
  397.         }
  398.     }
  399. }
  400.  
  401. void
  402. build_optional_terrain_type_menu()
  403. {
  404.     int t;
  405.     Str255 tmpstr;
  406.  
  407.     if (optterrmenu != nil && CountMItems(optterrmenu) < 1) {
  408.         for_all_terrain_types(t) {
  409.             if (!t_is_cell(t)) {
  410.                 sanitize_for_menu(t_type_name(t), tmpstr);
  411.                 AppendMenu(optterrmenu, tmpstr);
  412.                 EnableItem(optterrmenu, t);
  413.             }
  414.         }
  415.         if (CountMItems(optterrmenu) < 1)
  416.           optterrmenu = nil;
  417.     }
  418. }
  419.  
  420. /* Alter the feature menu to reflect a changed or new feature. */
  421.  
  422. void
  423. update_feature_menu(Feature *feature)
  424. {
  425.     char *desc;
  426.     Str255 tmpstr;
  427.  
  428.     desc = feature_desc(feature, spbuf);
  429.     sanitize_for_menu(desc, tmpstr);
  430.     if (feature->id + 1 > CountMItems(featuremenu)) {
  431.         AppendMenu(featuremenu, tmpstr);
  432.         EnableItem(featuremenu, feature->id + 1);
  433.     } else {
  434.         SetMenuItemText(featuremenu, feature->id + 1, tmpstr);
  435.     }
  436. }
  437.  
  438. /* This removes chars that are specially recognized by the Menu Manager.
  439.    Has to be done so that strange game-defined names don't scramble the
  440.    menus; innocuous because this affects only the appearance in the menu. */
  441.  
  442. static void
  443. sanitize_for_menu(char *str, Str255 outstr)
  444. {
  445.     int i = 0;
  446.  
  447.     /* Replace special chars with blanks. */
  448.     for (i = 0; str[i] != '\0' && i < 255; ++i) {
  449.         switch (str[i]) {
  450.             case ';':
  451.             case '!':
  452.             case '<':
  453.             case '/':
  454.             case '(':
  455.             /* I don't think closing parens are special, but since the
  456.                (presumed) matching open paren is gone, might as well get
  457.                rid of the close also. */
  458.             case ')':
  459.                 outstr[i + 1] = ' ';
  460.                 break;
  461.             default:
  462.                 outstr[i + 1] = str[i];
  463.                 break;
  464.         }
  465.     }
  466.     outstr[i + 1] = '\0';
  467.     /* Replace a leading hyphen with an underscore. */
  468.     if (outstr[1] == '-')
  469.       outstr[1] = '_';
  470.     outstr[0] = i;
  471. }
  472.  
  473. /* Decipher and do a menu command. */
  474.  
  475. void
  476. do_menu_command(long which)
  477. {
  478.     short menuid, menuitem, daRefNum;
  479.     Str255 daname;
  480.     WindowPtr win;
  481.     Map *map;
  482.  
  483.     menuid = HiWord(which);
  484.     menuitem = LoWord(which);
  485.     DGprintf("menu %d, item %d\n", menuid, menuitem);
  486.     map = map_from_window(FrontWindow());    
  487.     switch (menuid) {
  488.         case mApple:
  489.             switch (menuitem) {
  490.                 case miAppleAbout:
  491.                     do_about_box();
  492.                     break;
  493.                 case miAppleHelp:
  494.                     help_dialog(NULL);
  495.                     break;
  496.                 case miAppleInstructions:
  497.                     instructions_dialog();
  498.                     break;
  499.                 default:
  500.                     GetItem(GetMHandle(mApple), menuitem, daname);
  501.                     daRefNum = OpenDeskAcc(daname);
  502.             }
  503.             break;
  504.         case mFile:
  505.             switch (menuitem) {
  506.                 case miFileNew:
  507.                     /* (should reset state of everything first) */
  508.                     new_game_dialog();
  509.                     break;
  510.                 case miFileOpen:
  511.                     /* (should reset state of everything first) */
  512.                     open_game_dialog();
  513.                     break;
  514.                 case miFileConnect:
  515.                     connect_game_dialog();
  516.                     break;
  517.                 case miFileSave:
  518.                     save_the_game(FALSE, FALSE);
  519.                     break;
  520.                 case miFileSaveAs:    
  521.                     save_the_game(TRUE, FALSE);
  522.                     break;
  523.                 case miFilePreferences:
  524.                     set_preferences();
  525.                     break;
  526.                 case miFilePageSetup:
  527.                     do_page_setup_mi();
  528.                     break;
  529.                 case miFilePrintWindow:
  530.                     do_print_mi();
  531.                     break;
  532.                 case miFileResign:
  533.                     do_resign();
  534.                     break;
  535.                 case miFileQuit:
  536.                     quit_the_game();
  537.                     break;
  538.             }
  539.             break;
  540.         case mEdit:
  541.             if (SystemEdit(menuitem - 1))
  542.               break;
  543.             switch (menuitem)  {
  544.                 case miEditCut:
  545.                     if (FrontWindow() == commandwin) {
  546.                         te_cut(command_text);
  547.                     } else if(FrontWindow() == constructionwin) {
  548.                         te_cut(run_length_text);
  549.                     }
  550.                     break;
  551.                 case miEditCopy:
  552.                     if (FrontWindow() == commandwin) {
  553.                         te_copy(command_text);
  554.                     } else if(FrontWindow() == constructionwin) {
  555.                         te_copy(run_length_text);
  556.                     }
  557.                     break;
  558.                 case miEditPaste:
  559.                     if (FrontWindow() == commandwin) {
  560.                         te_paste(command_text);
  561.                     } else if (FrontWindow() == constructionwin) {
  562.                         te_paste(run_length_text);
  563.                     }
  564.                     break;
  565.                 case miEditClear:
  566.                     if (FrontWindow() == commandwin) {
  567.                         TEDelete(command_text);                        
  568.                     } else if (FrontWindow() == constructionwin) {
  569.                         TEDelete(run_length_text);                        
  570.                     }
  571.                     break;
  572.                 case miEditSelectAll:
  573.                     do_select_all_mi();
  574.                     break;
  575. #ifdef DESIGNERS
  576.                 case miEditDesign:
  577.                     do_design();
  578.                     break;
  579. #endif
  580.             }
  581.             break;
  582.         case mFind:
  583.             switch (menuitem) {
  584.                 case miFindPrevious:
  585.                     do_find_previous_mi();
  586.                     break;
  587.                 case miFindNext:
  588.                     do_find_next_mi();
  589.                     break;
  590.                 case miFindLocation:
  591.                     do_find_location_mi();
  592.                     break;
  593.                 case miFindUnitByName:
  594.                     do_find_unit_by_name_mi();
  595.                     break;
  596.                 case miFindSelected:
  597.                     do_find_selected_mi();
  598.                     break;
  599.             }
  600.             break;
  601.         case mPlay:
  602.             switch (menuitem) {
  603.                 case miPlayCloseup:
  604.                     do_closeup_mi();
  605.                     break;
  606.                 case miPlayMove:
  607.                     query_position_modally(MOVE_TO_MODAL);
  608.                     break;
  609.                 case miPlaySetFormation:
  610.                     query_position_modally(SET_FORMATION_MODAL);
  611.                     break;
  612.                 case miPlayReturn:
  613.                     do_return();
  614.                     break;
  615.                 case miPlayWake:
  616.                     do_wake();
  617.                     break;
  618.                 case miPlaySleep:
  619.                     do_sleep();
  620.                     break;
  621.                 case miPlayReserve:
  622.                     do_reserve();
  623.                     break;
  624.                 case miPlayBuild:
  625.                     do_build();
  626.                     break;
  627.                 case miPlayRepair:
  628.                     do_repair_mi();
  629.                     break;
  630.                 case miPlayAttack:
  631.                     do_attack_mi();
  632.                     break;
  633.                 case miPlayOverrun:
  634.                     do_overrun_mi();
  635.                     break;
  636.                 case miPlayFire:
  637.                     query_position_modally(FIRE_MODAL);
  638.                     break;
  639.                 case miPlayFireInto:
  640.                     do_fire_into_mi();
  641.                     break;
  642.                 case miPlayDetonate:
  643.                     do_detonate_mi();
  644.                     break;
  645.                 case miPlayTake:
  646.                     do_take_mi();
  647.                     break;
  648.                 case miPlayDrop:
  649.                     break;
  650.                 case miPlayGive:
  651.                     /* has submenu mSides */
  652.                     break;
  653.                 case miPlayDetach:
  654.                     do_detach();
  655.                     break;
  656.                 case miPlayDisband:
  657.                     do_disband();
  658.                     break;
  659.                 case miPlayAddTerrain:
  660.                     query_position_modally(ADD_TERRAIN_MODAL);
  661.                     break;
  662.                 case miPlayRemoveTerrain:
  663.                     query_position_modally(REMOVE_TERRAIN_MODAL);
  664.                     break;
  665.                 case miPlayRename:
  666.                     do_name();
  667.                     break;
  668.             }
  669.             break;
  670.         case mSides:
  671.             do_give_unit_mi(menuitem);
  672.             break;
  673.         case mSide:
  674.             switch (menuitem) {
  675.                 case miSideCloseup:
  676.                     break;
  677.                 case miSideFinishedTurn:
  678.                     finish_turn(dside);
  679.                     break;
  680.                 case miSideMoveOnClick:
  681.                     moveonclick_mi();
  682.                     break;
  683.                 case miSideAutoSelect:
  684.                     autoselect_mi();
  685.                     break;
  686.                 case miSideAutoFinish:
  687.                     /* Toggle auto-finish for turns. */
  688.                     set_autofinish(dside, !dside->autofinish);
  689.                     break;
  690.                 case miSideSound:
  691.                     playsounds = !playsounds;
  692.                     ui_update_state();
  693.                     save_preferences();
  694.                     break;
  695.                 case miSideRename:
  696.                     side_rename_dialog(dside);
  697.                     break;
  698.             }
  699.             break;
  700.         case mWindows:
  701.             switch (menuitem) {
  702.                 case miWindowsGame:
  703.                     if (gamewin == nil) {
  704.                         create_game_window();
  705.                     }
  706.                     ShowWindow(gamewin);
  707.                     SelectWindow(gamewin);
  708.                     break;
  709.                 case miWindowsNotices:
  710.                     if (noticewin == nil) {
  711.                         create_notice_window();
  712.                     }
  713.                     ShowWindow(noticewin);
  714.                     SelectWindow(noticewin);
  715.                     break;
  716.                 case miWindowsHistory:
  717.                     if (historywin == nil) {
  718.                         create_history_window();
  719.                     }
  720.                     ShowWindow(historywin);
  721.                     SelectWindow(historywin);
  722.                     break;
  723.                 case miWindowsConstruction:
  724.                     enable_construction();
  725.                     break;
  726.                 case miWindowsCommand:
  727.                     enable_command();
  728.                     break;
  729.                 /* should have agreements list etc handling here also */
  730.                 case miWindowsScores:
  731.                     scores_dialog();
  732.                     break;
  733.                 case miWindowsNewList:
  734.                     create_list();
  735.                     break;
  736.                 case miWindowsNewMap:
  737.                     create_map(5 /* should be a pref */);
  738.                     break;
  739.                 case miWindowsWorldMap:
  740.                     if (worldmapwin == nil) {
  741.                         int power, winwid = 200;
  742.  
  743.                         for (power = 0; power < NUMPOWERS; ++power) {
  744.                             if (area.width * hws[power] <= winwid
  745.                                 && area.width * hws[power+1] > winwid) break;
  746.                         }
  747.                         worldmap = create_map(power);
  748.                         worldmap->drawothermaps = TRUE;
  749.                         /* (should be in survey mode too?) */
  750.                         worldmapwin = worldmap->window;
  751.                     }
  752.                     ShowWindow(worldmapwin);
  753.                     SelectWindow(worldmapwin);
  754.                     break;
  755.                 default:
  756.                     win = winmenuwins[menuitem - miWindowsFirst];
  757.                     if (win != nil) {
  758.                         SelectWindow(win);
  759.                     }
  760.                     break;
  761.             }
  762.             break;
  763.         case mViewMap:
  764.             if (map == NULL) break;
  765.             switch (menuitem)  {
  766.                 case miViewCloser:
  767.                     magnify_map(map, 1);
  768.                     break;
  769.                 case miViewFarther:
  770.                     magnify_map(map, -1);
  771.                     break;
  772.                 case miViewNames:
  773.                     toggle_map_names(map);
  774.                     break;
  775.                 case miViewPeople:
  776.                     toggle_map_people(map);
  777.                     break;
  778.                 case miViewElevations:
  779.                     toggle_map_elevations(map);
  780.                     break;
  781.                 case miViewDaylight:
  782.                     toggle_map_lighting(map);
  783.                     break;
  784.                 case miViewCoverage:
  785.                     toggle_map_coverage(map);
  786.                     break;
  787.                 case miViewGrid:
  788.                     toggle_map_grid(map);
  789.                     break;
  790.                 case miViewTopline:
  791.                     toggle_map_topline(map);
  792.                     break;
  793.                 case miViewTopunit:
  794.                     toggle_map_topunit(map);
  795.                     break;
  796.                 case miViewOtherMaps:
  797.                     toggle_map_other_maps(map);
  798.                     break;
  799.             }
  800.             break;
  801.         case mViewWeather:
  802.             if (map == NULL) break;
  803.             switch (menuitem)  {
  804.                 case miWeatherTemperature:
  805.                     toggle_map_temperature(map);
  806.                     break;
  807.                 case miWeatherWinds:
  808.                     toggle_map_winds(map);
  809.                     break;
  810.                 case miWeatherClouds:
  811.                     toggle_map_clouds(map);
  812.                     break;
  813.                 case miWeatherStorms:
  814.                     toggle_map_storms(map);
  815.                     break;
  816.             }
  817.             break;
  818.         case mViewAngles:
  819.             if (map == NULL) break;
  820.             switch (menuitem)  {
  821.                 case miAngle15:
  822.                     set_view_angle(map->vp, 15);
  823.                     force_map_update(map);
  824.                     break;
  825.                 case miAngle30:
  826.                     set_view_angle(map->vp, 30);
  827.                     force_map_update(map);
  828.                     break;
  829.                 case miAngle90:
  830.                     set_view_angle(map->vp, 90);
  831.                     force_map_update(map);
  832.                     break;
  833.             }
  834.             break;
  835.         case mViewList:
  836.             switch (menuitem)  {
  837.                 case miViewByType:
  838.                     set_list_sorting(list_from_window(FrontWindow()), bytype, menuitem);
  839.                     break;
  840.                 case miViewByName:
  841.                     set_list_sorting(list_from_window(FrontWindow()), byname, menuitem);
  842.                     break;
  843.                 case miViewBySide:
  844.                     set_list_sorting(list_from_window(FrontWindow()), byside, menuitem);
  845.                     break;
  846.                 case miViewByActOrder:
  847.                     set_list_sorting(list_from_window(FrontWindow()), byactorder, menuitem);
  848.                     break;
  849.                 case miViewByLocation:
  850.                     set_list_sorting(list_from_window(FrontWindow()), bylocation, menuitem);
  851.                     break;
  852.                 case miViewIconSize:
  853.                     toggle_list_large_icons(list_from_window(FrontWindow()));
  854.                     break;
  855.             }
  856.             break;
  857.         case mAITypes:
  858.             switch (menuitem) {
  859.                 case 1:
  860.                     if (side_has_ai(dside)) {
  861.                         set_side_ai(dside, NULL);
  862.                     }
  863.                     break;
  864.                 case 2:
  865.                     if (!side_has_ai(dside)) {
  866.                         set_side_ai(dside, "mplayer");
  867.                     }
  868.                     break;
  869.             }
  870.             break;
  871.         case mMagnifications:
  872.             if (map == NULL) break;
  873.             set_map_mag(map, menuitem - 1);
  874.             break;
  875.         case mMaterialTypes:
  876.             if (map == NULL) break;
  877.             toggle_map_materials(map, menuitem - 1);
  878.             break;
  879.         case mOptTerrainTypes:
  880.             if (map == NULL) break;
  881.             toggle_map_aux_terrain(map, map->auxterraintypes[menuitem]);
  882.             break;
  883.     }
  884.     HiliteMenu(0);
  885. }
  886.  
  887. /* Display the "About..." box. */
  888.  
  889. void
  890. do_about_box()
  891. {
  892.     short ditem;
  893.     Str255 tmpstr;
  894.     WindowPtr win;
  895.     PicHandle pic;
  896.     short itemtype;  Handle itemhandle;  Rect itemrect;
  897.  
  898.     win = GetNewDialog(dAbout, NULL, (DialogPtr) -1L);
  899.     /* Fill in the kernel's version and copyright. */
  900.     GetDItem(win, diAboutVersion, &itemtype, &itemhandle, &itemrect);
  901.     c2p(version_string(), tmpstr);
  902.     SetIText(itemhandle, tmpstr);
  903.     GetDItem(win, diAboutCopyright, &itemtype, &itemhandle, &itemrect);
  904.     c2p(copyright_string(), tmpstr);
  905.     SetIText(itemhandle, tmpstr);
  906.     /* Substitute a color picture if we've got a color/gray screen. */
  907.     if (hasColorQD) {
  908.         GetDItem(win, diAboutPicture, &itemtype, &itemhandle, &itemrect);
  909.         if ((pic = (PicHandle) GetResource('PICT', pSplashColor)) != nil) {
  910.             SetDItem(win, diAboutPicture, itemtype, (Handle) pic, &itemrect);
  911.         }
  912.     }
  913.     ShowWindow(win);
  914.     SelectWindow(win);
  915.     draw_default_button(win, diAboutOK);
  916.     SetCursor(&QD(arrow));
  917.     ModalDialog(NULL, &ditem);
  918.     /* Just return, no matter what input. */
  919.     HideWindow(win);
  920.     DisposDialog(win);
  921. }
  922.  
  923. /* This routine does both "save" and "save as". */
  924.  
  925. void
  926. save_the_game(int askname, int quitting)
  927. {
  928.     Point pnt;
  929.     char namebuf[256];
  930.     Str255 tmpstr;
  931.     SFReply reply;
  932.  
  933. #ifdef DESIGNERS
  934.     /* Do the selective save only if we're not shutting down Xconq. */
  935.     if (dside->designer && !quitting) {
  936.         designer_save_dialog();
  937.         return;
  938.     }
  939. #endif
  940.     if (askname || cursavename == NULL) {
  941.         if (cursavename == NULL)
  942.           cursavename = saved_game_filename();
  943.         /* Collect the file and path to save to. */
  944.         SetPt(&pnt, 100, 100);
  945.         c2p(cursavename, tmpstr);
  946.         SFPutFile(pnt, "\p", tmpstr, /*(DlgHookProcPtr)*/ nil, &reply);
  947.         if (!reply.good)
  948.           return;
  949.         /* Make the location of the file be the current volume. */
  950.         SetVol(reply.fName, reply.vRefNum);
  951.         p2c(((char *) reply.fName), namebuf);
  952.         cursavename = copy_string(namebuf);
  953.     }
  954.     SetCursor(*watchcursor);
  955.     write_entire_game_state(cursavename);
  956.     set_game_file_type(cursavename);
  957.     SetCursor(&QD(arrow));
  958. }
  959.  
  960. /*THPrint printrecordhandle = nil;*/
  961.  
  962. void
  963. maybe_init_print()
  964. {
  965. /*    if (printrecordhandle == nil) {
  966.         printrecordhandle = (THPrint) NewHandle(sizeof(TPrint));
  967.         PrOpen();
  968.         PrintDefault(printrecordhandle);
  969.     } */
  970. }
  971.  
  972. void
  973. do_page_setup_mi()
  974. {
  975.     maybe_init_print();
  976. /*    PrStlDialog(printrecordhandle); */
  977. }
  978.  
  979. /* Handle printing.  What gets printed depends on which window is in front. */
  980.  
  981. static void
  982. do_print_mi()
  983. {
  984.     Map *map;
  985.     List *list;
  986.  
  987.     maybe_init_print();
  988. /*    if (!PrJobDialog(printrecordhandle)) return; */
  989.     if ((map = map_from_window(FrontWindow())) != NULL) {
  990.         print_map(map);
  991.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  992.         print_list(list);
  993.     } else {
  994.         /* (should at least be able to print help) */
  995.     }
  996. }
  997.  
  998. static void
  999. resign_the_game(int forced)
  1000. {
  1001.     Str255 tmpstr;
  1002.  
  1003.     sprintf(tmpbuf, "Other players");
  1004.     c2p(tmpbuf, tmpstr);
  1005.     ParamText(tmpstr, "\p", "\p", "\p");
  1006.     switch (CautionAlert(aResignGame, nil)) {
  1007.         case aiResignGameOK:
  1008.             forcedtoresign = forced;
  1009.             resign_game(dside, NULL);
  1010.             break;
  1011.         case aiResignGameWillingToDraw:
  1012.             set_willing_to_draw(dside, TRUE);
  1013.             break;
  1014.         case aiResignGameCancel:
  1015.             break;
  1016.     }
  1017. }
  1018.  
  1019. /* Attempt to quit. */
  1020.  
  1021. void
  1022. quit_the_game()
  1023. {
  1024.     int confirmresign = FALSE;
  1025.  
  1026. #ifdef DESIGNERS
  1027.     /* If we're designing, need only confirm the save before quitting;
  1028.        no resignation requirement. */
  1029.     if (dside->designer) {
  1030.         switch (CautionAlert(aDesignerQuitGame, nil)) {
  1031.             case aiDesignerQuitGameOK:
  1032.                 SetCursor(*watchcursor);
  1033.                 save_the_game(FALSE, TRUE);
  1034.                 SetCursor(&QD(arrow));
  1035.                 /* Fall through to exit. */
  1036.             case aiDesignerQuitGameDontSave:
  1037.                 ExitToShell();
  1038.                 break;
  1039.             case aiDesignerQuitGameCancel:
  1040.                 break;
  1041.         }
  1042.         return;
  1043.     }
  1044. #endif /* DESIGNERS */
  1045.     if (endofgame) {
  1046.         /* Game is already over, nothing to save, just leave. */
  1047.         ExitToShell();
  1048.     } else if (!gamestatesafe || !interfacestatesafe) {
  1049.         switch (CautionAlert(aQuitGame, nil)) {
  1050.             case aiQuitGameOK:
  1051.                 if (all_others_willing_to_save(dside)) {
  1052.                     SetCursor(*watchcursor);
  1053.                     save_the_game(FALSE, TRUE);
  1054.                     SetCursor(&QD(arrow));
  1055.                     ExitToShell();
  1056.                 } else {
  1057.                     set_willing_to_save(dside, TRUE);
  1058.                     /* (should warn that not all were willing to save) */
  1059.                 }
  1060.                 break;
  1061.             case aiQuitGameDontSave:
  1062.                 if (all_others_willing_to_quit(dside)) {
  1063.                     set_willing_to_draw(dside, TRUE);
  1064.                 } else {
  1065.                     /* Can only get out by resigning. */
  1066.                     confirmresign = TRUE;
  1067.                 }
  1068.                 break;
  1069.             case aiQuitGameCancel:
  1070.                 break;
  1071.         }
  1072.     } else {
  1073.         /* (should still confirm that we're not avoiding our fate?) */
  1074.         ExitToShell();
  1075.     }
  1076.     if (confirmresign) {
  1077.         resign_the_game(TRUE);
  1078.     }
  1079. }
  1080.  
  1081. static void
  1082. te_cut(TEHandle hdl)
  1083. {
  1084.     if (ZeroScrap() == noErr) {
  1085.         TECut(hdl);
  1086.         if (TEToScrap() != noErr)
  1087.           ZeroScrap();
  1088.     }
  1089. }
  1090.  
  1091. static void
  1092. te_copy(TEHandle hdl)
  1093. {
  1094.     if (ZeroScrap() == noErr) {
  1095.         TECopy(hdl);
  1096.         if (TEToScrap() != noErr)
  1097.           ZeroScrap();
  1098.     }
  1099. }
  1100.  
  1101. static void
  1102. te_paste(TEHandle hdl)
  1103. {
  1104.     if (TEFromScrap() == noErr) {
  1105.         TEPaste(hdl);
  1106.     }
  1107. }
  1108.  
  1109. static void
  1110. do_select_all_mi()
  1111. {
  1112.     Map *map;
  1113.     Unit *unit;
  1114.  
  1115.     if (FrontWindow() == commandwin) {
  1116.         /* (should add this) */
  1117.     } else if (FrontWindow() == constructionwin) {
  1118.         /* (should add this) */
  1119.     } else if ((map = map_from_window(FrontWindow())) != NULL) {
  1120.         for_all_units(unit) {
  1121.             if (side_may_select(unit)) {
  1122.                 select_unit_on_map(map, unit);
  1123.             }
  1124.         }
  1125.         /* Do all the drawing at once. */
  1126.         draw_selections(map);
  1127.     } else if (0 /* is list */) {
  1128.     }
  1129. }
  1130.  
  1131. static void
  1132. do_find_previous_mi()
  1133. {
  1134.     Map *map;
  1135.     
  1136.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1137.         select_previous_unit(map);
  1138.     }
  1139. }
  1140.  
  1141. static void
  1142. do_find_next_mi()
  1143. {
  1144.     Map *map;
  1145.     
  1146.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1147.         select_next_mover(map);
  1148.     }
  1149. }
  1150.  
  1151. /* (should ask for x,y coords, focus/center on that position) */
  1152.  
  1153. static void
  1154. do_find_location_mi()
  1155. {
  1156.     Map *map;
  1157.  
  1158.     beep();    
  1159.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1160.     }
  1161. }
  1162.  
  1163. /* (should ask for a textual name/select from a gazetteer, scroll to that unit) */
  1164.  
  1165. static void
  1166. do_find_unit_by_name_mi()
  1167. {
  1168.     Map *map;
  1169.     
  1170.     beep();    
  1171.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1172.     }
  1173. }
  1174.  
  1175. static void
  1176. do_find_selected_mi()
  1177. {
  1178.     Map *map;
  1179.     List *list;
  1180.     UnitCloseup *closeup;
  1181.     
  1182.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1183.         int i;
  1184.         Unit *unit;
  1185.  
  1186.         /* Scroll to the first valid selected unit we find. */
  1187.         for (i = 0; i < map->numselections; ++i) {
  1188.             unit = map->selections[i];
  1189.             if (in_play(unit)) {
  1190.                 scroll_to_unit(map, unit);
  1191.                 return;
  1192.             }
  1193.         }
  1194.         beep();
  1195.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  1196.         scroll_to_selected_unit_in_list(list);
  1197.     } else if ((closeup = unit_closeup_from_window(FrontWindow())) != NULL) {
  1198.         if (closeup->unit != NULL)
  1199.           scroll_best_map_to_unit(closeup->unit);
  1200.     } else if (constructionwin == FrontWindow()) {
  1201.         scroll_to_selected_construction_unit();
  1202.     } else {
  1203.         /* nothing to do */
  1204.     }
  1205. }
  1206.  
  1207. /* Menu items/commands for unit play action. */
  1208.  
  1209. void
  1210. apply_to_all_selected(int (*fn)(Unit *unit), int beepfailure)
  1211. {
  1212.     int i, rslt, numcould = 0, numnot = 0;
  1213.     Map *map;  List *list;  UnitCloseup *closeup;
  1214.     Unit *unit;
  1215.  
  1216.     if (fn == NULL)
  1217.       return;
  1218.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1219.         for (i = 0; i < map->numselections; ++i) {
  1220.             unit = map->selections[i];
  1221.             if (in_play(unit)) {
  1222.                 rslt = (*fn)(unit);
  1223.                 if (rslt)
  1224.                   ++numcould;
  1225.                 else
  1226.                   ++numnot;
  1227.             }
  1228.         }
  1229.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  1230.         if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
  1231.             rslt = (*fn)(unit);
  1232.             if (rslt)
  1233.               ++numcould;
  1234.             else
  1235.               ++numnot;
  1236.         }
  1237.     } else if ((closeup = unit_closeup_from_window(FrontWindow())) != NULL) {
  1238.         if ((unit = closeup->unit) != NULL) {
  1239.             rslt = (*fn)(unit);
  1240.             if (rslt)
  1241.               ++numcould;
  1242.             else
  1243.               ++numnot;
  1244.         }
  1245.     }
  1246.     /* If everybody that was asked to do this couldn't, beep once. */
  1247.     if (beepfailure && numcould == 0 && numnot > 0)
  1248.       beep();
  1249. }
  1250.  
  1251. static void
  1252. do_closeup_mi()
  1253. {
  1254.     int i;
  1255.     Map *map;  List *list;  UnitCloseup *unitcloseup;
  1256.     Unit *unit;
  1257.     
  1258.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1259.         for (i = 0; i < map->numselections; ++i) {
  1260.             if ((unit = map->selections[i]) != NULL) {
  1261.                 if ((unitcloseup = find_unit_closeup(unit)) != NULL) {
  1262.                     ShowWindow(unitcloseup->window);
  1263.                     SelectWindow(unitcloseup->window);
  1264.                 } else {
  1265.                     create_unit_closeup(unit);
  1266.                 }
  1267.             }
  1268.         }
  1269.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  1270.         if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
  1271.             if ((unitcloseup = find_unit_closeup(unit)) != NULL) {
  1272.                 ShowWindow(unitcloseup->window);
  1273.                 SelectWindow(unitcloseup->window);
  1274.             } else {
  1275.                 create_unit_closeup(unit);
  1276.             }
  1277.         }
  1278.     } else if ((unitcloseup = unit_closeup_from_window(FrontWindow())) != NULL) {
  1279.         if ((unit = unitcloseup->unit) != NULL) {
  1280.             force_update(unitcloseup->window);
  1281.         }
  1282.     }
  1283. }
  1284.  
  1285. static void
  1286. do_move_mi()
  1287. {
  1288.     do_move_to();
  1289. }
  1290.  
  1291. static void
  1292. do_repair_mi()
  1293. {
  1294.     apply_to_all_selected(do_one_repair, 0);    
  1295. }
  1296.  
  1297. static int
  1298. do_one_repair(Unit *unit)
  1299. {
  1300.     return TRUE;
  1301. }
  1302.  
  1303. /* (should find one unit to attack, do modal dialog if != 1) */
  1304.  
  1305. static void
  1306. do_attack_mi()
  1307. {
  1308.     int i;
  1309.     Map *map;
  1310.     Unit *atker, *other;
  1311.     
  1312.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1313.         for (i = 0; i < map->numselections; ++i) {
  1314.             if ((atker = map->selections[i]) != NULL) {
  1315.                 for_all_units(other) {
  1316.                     if (other != atker
  1317.                         && other->side != atker->side
  1318.                         && distance(atker->x, atker->y, other->x, other->y) == 1) {
  1319.                             prep_attack_action(atker, atker, other, 100);
  1320.                             break;
  1321.                     }
  1322.                 }
  1323.             }
  1324.         }
  1325.     }
  1326. }
  1327.  
  1328. void
  1329. do_attack_command()
  1330. {
  1331.     int i, numcould = 0, numnot = 0;
  1332.     Point target;
  1333.     Map *map;
  1334.     Unit *atker, *other;
  1335.     
  1336.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1337.         GetMouse(&target);
  1338.         m_nearest_unit(map, target.h, target.v, &other);
  1339.         if (other != NULL) {
  1340.             for (i = 0; i < map->numselections; ++i) {
  1341.                 if ((atker = map->selections[i]) != NULL) {
  1342.                     if (other != atker
  1343.                         && other->side != atker->side) {
  1344.                         if (distance(atker->x, atker->y, other->x, other->y) <= 1
  1345.                             && valid(check_attack_action(atker, atker, other, 100))) {
  1346.                             prep_attack_action(atker, atker, other, 100);
  1347.                             ++numcould;
  1348.                         } else if (valid(check_fire_at_action(atker, atker, other, -1))) {
  1349.                             prep_fire_at_action(atker, atker, other, -1);
  1350.                             ++numcould;
  1351.                         } else {
  1352.                             ++numnot;
  1353.                         }
  1354.                     } else {
  1355.                     }
  1356.                 }
  1357.             }
  1358.         } else {
  1359.             /* (should let units fire into empty cell) */
  1360.         }
  1361.     }
  1362.     /* If nobody could do the action, beep once. */
  1363.     if (numcould == 0 && numnot > 0) beep();
  1364. }
  1365.  
  1366. static void
  1367. do_overrun_mi()
  1368. {
  1369.     /* (should loop until mouse clicked in map) */
  1370.     beep();
  1371. }
  1372.  
  1373. int
  1374. do_fire_command()
  1375. {
  1376.     int i, numcould = 0, numnot = 0;
  1377.     Point target;
  1378.     Map *map;
  1379.     Unit *atker, *other;
  1380.     
  1381.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1382.         GetMouse(&target);
  1383.         m_nearest_unit(map, target.h, target.v, &other);
  1384.         if (other != NULL) {
  1385.             for (i = 0; i < map->numselections; ++i) {
  1386.                 if ((atker = map->selections[i]) != NULL && valid_selection(atker)) {
  1387.                     if (other != atker
  1388.                         && other->side != atker->side
  1389.                         && valid(check_fire_at_action(atker, atker, other, -1))) {
  1390.                         prep_fire_at_action(atker, atker, other, -1);
  1391.                         ++numcould;
  1392.                     } else {
  1393.                         ++numnot;
  1394.                     }
  1395.                 }
  1396.             }
  1397.         } else {
  1398.             /* Just error out.  To bombard a cell, the player must do a fire-into
  1399.                command.  It might be useful to add an option that automatically tries
  1400.                firing into if no targets are visible, but if a player was trying to
  1401.                fire at a unit but got the cell slightly wrong, then the fire-into will
  1402.                happen anyway and the player loses the acp. */
  1403.             beep();
  1404.         }
  1405.     }
  1406.     /* If nobody could do the action, beep once. */
  1407.     if (numcould == 0 && numnot > 0) {
  1408.         beep();
  1409.         return FALSE;
  1410.     } else {
  1411.         return TRUE;
  1412.     }
  1413. }
  1414.  
  1415. static void
  1416. do_fire_into_mi()
  1417. {
  1418.     if (map_modal == NO_MODAL) {
  1419.         map_modal = FIRE_INTO_MODAL;
  1420.     }
  1421. }
  1422.  
  1423. int
  1424. do_fire_into_command()
  1425. {
  1426.     int x, y, i, numcould = 0, numnot = 0;
  1427.     Point target;
  1428.     Map *map;
  1429.     Unit *atker;
  1430.     
  1431.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1432.         GetMouse(&target);
  1433.         if (m_nearest_cell(map, target.h, target.v, &x, &y)) {
  1434.             for (i = 0; i < map->numselections; ++i) {
  1435.                 if ((atker = map->selections[i]) != NULL && valid_selection(atker)) {
  1436.                     if (valid(check_fire_into_action(atker, atker, x, y, 0, -1))) {
  1437.                         prep_fire_into_action(atker, atker, x, y, 0, -1);
  1438.                         ++numcould;
  1439.                     } else {
  1440.                         ++numnot;
  1441.                     }
  1442.                 }
  1443.             }
  1444.         } else {
  1445.             beep();
  1446.         }
  1447.     }
  1448.     /* If nobody could do the action, beep once. */
  1449.     if (numcould == 0 && numnot > 0) {
  1450.         beep();
  1451.         return FALSE;
  1452.     } else {
  1453.         return TRUE;
  1454.     }
  1455. }
  1456.  
  1457. /* (should decide how to detonate based on selections and modal input) */
  1458.  
  1459. int
  1460. do_one_detonate(Unit *unit)
  1461. {
  1462.     if (valid(check_detonate_action(unit, unit, unit->x, unit->y, unit->z))) {
  1463.         prep_detonate_action(unit, unit, unit->x, unit->y, unit->z);
  1464.         return TRUE;
  1465.     }
  1466.     return FALSE;
  1467. }
  1468.  
  1469. static void
  1470. do_detonate_mi()
  1471. {
  1472.     apply_to_all_selected(do_one_detonate, TRUE);
  1473. }
  1474.  
  1475. /* This command samples the current mouse to get the desired detonate location. */
  1476.  
  1477. void
  1478. do_detonate_command()
  1479. {
  1480.     int i, x, y;
  1481.     Point detpoint;
  1482.     Map *map;
  1483.     Unit *unit;
  1484.     
  1485.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1486.         GetMouse(&detpoint);
  1487.         m_nearest_cell(map, detpoint.h, detpoint.v, &x, &y);
  1488.         for (i = 0; i < map->numselections; ++i) {
  1489.             if ((unit = map->selections[i]) != NULL) {
  1490.                 prep_detonate_action(unit, unit, x, y, unit->z);
  1491.             }
  1492.         }
  1493.     }
  1494. }
  1495.  
  1496. int
  1497. do_one_give(Unit *unit)
  1498. {
  1499.     give_supplies(unit, NULL, NULL);
  1500.     return 0;
  1501. }
  1502.  
  1503. Side *tmpcmdside;
  1504.  
  1505. int
  1506. do_one_give_unit(Unit *unit)
  1507. {
  1508.     if (unit->side == tmpcmdside)
  1509.       return FALSE;
  1510. #ifdef DESIGNERS
  1511.     if (dside->designer) {
  1512.         designer_change_side(unit, tmpcmdside);
  1513.         return TRUE;
  1514.     }
  1515. #endif /* DESIGNERS */
  1516.     prep_change_side_action(unit, unit, tmpcmdside);
  1517.     return TRUE;
  1518. }
  1519.  
  1520. static void
  1521. do_give_unit_mi(int mi)
  1522. {
  1523.     Side *side = side_n(mi); /* note that side_n returns NULL for mi == numsides */
  1524.     
  1525.     apply_to_all_selected(do_one_give_unit, TRUE);
  1526. }
  1527.  
  1528. static void
  1529. moveonclick_mi()
  1530. {
  1531.     Map *frontmap = map_from_window(FrontWindow());
  1532.  
  1533.     if (frontmap) {
  1534.         frontmap->moveonclick = !frontmap->moveonclick;
  1535.         /* (should force updates of map windows to reflect?) */
  1536.     } else {
  1537.         defaultmoveonclick = !defaultmoveonclick;
  1538.     }
  1539. }
  1540.  
  1541. int
  1542. do_one_take(Unit *unit)
  1543. {
  1544.     take_supplies(unit, NULL, NULL);
  1545.     return TRUE;
  1546. }
  1547.  
  1548. static void
  1549. do_take_mi()
  1550. {
  1551.     apply_to_all_selected(do_one_take, TRUE);
  1552. }
  1553.  
  1554. static void
  1555. autoselect_mi()
  1556. {
  1557.     Map *frontmap = map_from_window(FrontWindow());
  1558.     extern Unit *curunit;
  1559.  
  1560.     if (frontmap) {
  1561.         frontmap->autoselect = !frontmap->autoselect;
  1562.         frontmap->curunit = NULL; /* maybe not a good idea? */
  1563.         /* (should force updates of map windows to reflect?) */
  1564.     } else {
  1565.         defaultautoselect = !defaultautoselect;
  1566.     }
  1567. }
  1568.  
  1569. static void
  1570. adjust_menu_item(MenuHandle menu, int item, int value)
  1571. {
  1572.     if (value)
  1573.       EnableItem(menu, item);
  1574.     else
  1575.       DisableItem(menu, item);
  1576. }
  1577.  
  1578. /* The state of menu items changes to reflect selected units, etc. */
  1579.  
  1580. void
  1581. adjust_menus()
  1582. {
  1583.     int i, m, t, numwins, menus_useful, numitems, has_text, offset;
  1584.     MenuHandle menu;
  1585.     Map *frontmap;
  1586.     List *frontlist;
  1587.     UnitCloseup *frontcloseup;
  1588.     Unit *unit;
  1589.     WindowPtr frontwin;
  1590.  
  1591.     frontwin = FrontWindow();
  1592.     frontmap = map_from_window(frontwin);
  1593.     frontlist = list_from_window(frontwin);
  1594.     frontcloseup = unit_closeup_from_window(frontwin);
  1595.     menus_useful =
  1596.         (gamedefined
  1597.          && ((!beforestart && !endofgame)
  1598.               || (gameinited
  1599. #ifdef DESIGNERS
  1600.                   && dside->designer
  1601. #endif /* DESIGNERS */
  1602.                   )));
  1603.     /* Certain menus need to be built after the game is running. */
  1604.     if (menus_useful) {
  1605.         build_material_type_menu();
  1606.         build_side_menu();
  1607.         build_ai_type_menu();
  1608.     }
  1609. #if 0
  1610.     if (is_da_window(FrontWindow())) {
  1611.         if ((menu = GetMHandle(mEdit)) != nil) {
  1612.         }
  1613.         return;
  1614.     }
  1615. #endif
  1616.     menu = GetMHandle(mApple);
  1617.     if (menu != nil) {
  1618.         adjust_menu_item(menu, miAppleInstructions, gamedefined);
  1619.     }
  1620.     menu = GetMHandle(mFile);
  1621.     if (menu != nil) {
  1622.         /* Availability of file menu items depends on whether we're in a game. */
  1623.         adjust_menu_item(menu, miFileNew, !gamedefined);
  1624.         adjust_menu_item(menu, miFileOpen, !gamedefined);
  1625.         adjust_menu_item(menu, miFileConnect, !gamedefined);
  1626.         adjust_menu_item(menu, miFileSave, menus_useful);
  1627.         adjust_menu_item(menu, miFileSaveAs, menus_useful);
  1628.         adjust_menu_item(menu, miFilePrintWindow, (frontmap != NULL || frontlist != NULL));
  1629.         adjust_menu_item(menu, miFileResign, menus_useful && dside->ingame);
  1630.     }
  1631.     menu = GetMHandle(mEdit);
  1632.     if (menu != nil) {
  1633.         /* Edit menu is always available, but individual items may be disabled. */
  1634.         adjust_menu_item(menu, miEditUndo, FALSE);
  1635.         has_text = FALSE;
  1636.         if (frontwin == commandwin) {
  1637.             has_text = ((*command_text)->selStart < (*command_text)->selEnd);
  1638.         } else if (frontwin == constructionwin) {
  1639.             has_text = ((*run_length_text)->selStart < (*run_length_text)->selEnd);
  1640.         }
  1641.         adjust_menu_item(menu, miEditCut, has_text);
  1642.         adjust_menu_item(menu, miEditCopy, has_text);
  1643.         adjust_menu_item(menu, miEditPaste, (GetScrap(nil, 'TEXT', (long *) &offset) > 0));
  1644.         adjust_menu_item(menu, miEditClear, has_text);
  1645.         adjust_menu_item(menu, miEditSelectAll, (frontmap != NULL || frontlist != NULL || has_text));
  1646.         if (menus_useful) {
  1647. #ifdef DESIGNERS
  1648.             CheckItem(menu, miEditDesign, dside->designer);
  1649. #else
  1650.             DisableItem(menu, miEditDesign);
  1651. #endif /* DESIGNERS */
  1652.         }
  1653.     }
  1654.     menu = GetMHandle(mFind);
  1655.     if (menu != nil) {
  1656.         if (gameinited) {
  1657.             EnableItem(menu, 0);
  1658.             adjust_menu_item(menu, miFindPrevious, menus_useful);
  1659.             adjust_menu_item(menu, miFindNext, menus_useful);
  1660.             adjust_menu_item(menu, miFindLocation, menus_useful);
  1661.             adjust_menu_item(menu, miFindUnitByName, TRUE);
  1662.             adjust_menu_item(menu, miFindSelected, (frontmap != NULL || frontlist != NULL || frontcloseup != NULL || constructionwin == frontwin));
  1663.         } else {
  1664.             /* We're not even in a game yet, turn entire menu off. */
  1665.             DisableItem(menu, 0);
  1666.         }
  1667.     }
  1668.     menu = GetMHandle(mPlay);
  1669.     if (menu != nil) {
  1670.         if (gameinited) {
  1671.             EnableItem(menu, 0);
  1672.             /* Disable everything first, then selectively re-enable. */
  1673.             DisableItem(menu, miPlayCloseup);
  1674.             DisableItem(menu, miPlayMove);
  1675.             DisableItem(menu, miPlaySetFormation);
  1676.             DisableItem(menu, miPlayReturn);
  1677.             DisableItem(menu, miPlayWake);
  1678.             DisableItem(menu, miPlaySleep);
  1679.             DisableItem(menu, miPlayReserve);
  1680.             DisableItem(menu, miPlayDelay);
  1681.             DisableItem(menu, miPlayBuild);
  1682.             DisableItem(menu, miPlayRepair);
  1683.             DisableItem(menu, miPlayAttack);
  1684.             DisableItem(menu, miPlayOverrun);
  1685.             DisableItem(menu, miPlayFire);
  1686.             DisableItem(menu, miPlayFireInto);
  1687.             DisableItem(menu, miPlayDetonate);
  1688.             DisableItem(menu, miPlayTake);
  1689.             DisableItem(menu, miPlayDrop);
  1690.             DisableItem(menu, miPlayGive);
  1691.             DisableItem(menu, miPlayDetach);
  1692.             DisableItem(menu, miPlayDisband);
  1693.             DisableItem(menu, miPlayAddTerrain);
  1694.             DisableItem(menu, miPlayRemoveTerrain);
  1695.             DisableItem(menu, miPlayRename);
  1696.             /* Note that command enabling is accumulative for all units. */
  1697.             if (frontmap != NULL) {
  1698.                 for (i = 0; i < frontmap->numselections; ++i) {
  1699.                     if ((unit = frontmap->selections[i]) != NULL) {
  1700.                         enable_commands_for_unit(menu, unit);
  1701.                     }
  1702.                 }
  1703.             } else if (frontlist != NULL) {
  1704.                 if ((unit = (Unit *) selected_unit_in_list(frontlist)) != NULL) {
  1705.                     enable_commands_for_unit(menu, unit);
  1706.                 }
  1707.             } else if (frontcloseup != NULL) {
  1708.                 if ((unit = frontcloseup->unit) != NULL) {
  1709.                     enable_commands_for_unit(menu, unit);
  1710.                 }
  1711.             }
  1712.         } else {
  1713.             /* We're not even in a valid game state yet, turn entire menu off. */
  1714.             DisableItem(menu, 0);
  1715.         }
  1716.     }
  1717.     menu = GetMHandle(mSide);
  1718.     if (menu != nil) {
  1719.         if (menus_useful) {
  1720.             EnableItem(menu, 0);
  1721.             CheckItem(menu, miSideMoveOnClick,
  1722.                       (frontmap ? frontmap->moveonclick : defaultmoveonclick));
  1723.             CheckItem(menu, miSideAutoSelect,
  1724.                       (frontmap ? frontmap->autoselect : defaultautoselect));
  1725.             CheckItem(menu, miSideAutoFinish, dside->autofinish);
  1726.             CheckItem(menu, miSideSound, playsounds);
  1727.             if (dside->nameslocked) {
  1728.                 DisableItem(menu, miSideRename);
  1729.             } else {
  1730.                 EnableItem(menu, miSideRename);
  1731.             }
  1732.         } else {
  1733.             /* We're not even in a game yet, turn entire menu off. */
  1734.             DisableItem(menu, 0);
  1735.         }
  1736.     }
  1737.     menu = GetMHandle(mWindows);
  1738.     if (menu != nil) {
  1739.         if (gameinited) {
  1740.             EnableItem(menu, 0);
  1741.             /* Every item is always enabled. (should be, anyway) */
  1742.             CheckItem(menu, miWindowsGame,
  1743.                 (gamewin && ((WindowPeek) gamewin)->visible));
  1744.             CheckItem(menu, miWindowsNotices,
  1745.                 (noticewin && ((WindowPeek) noticewin)->visible));
  1746.             CheckItem(menu, miWindowsHistory,
  1747.                 (historywin && ((WindowPeek) historywin)->visible));
  1748.             CheckItem(menu, miWindowsCommand,
  1749.                 (commandwin && ((WindowPeek) commandwin)->visible));
  1750.             if (any_construction_possible()) {
  1751.                 EnableItem(menu, miWindowsConstruction);
  1752.                 CheckItem(menu, miWindowsConstruction,
  1753.                     (constructionwin && ((WindowPeek) constructionwin)->visible));
  1754.             } else {
  1755.                 DisableItem(menu, miWindowsConstruction);
  1756.             }
  1757.             numwins = CountMItems(menu) - miWindowsFirst;
  1758.             for (i = 0; i < numwins; ++i) {
  1759.                 CheckItem(menu, i + miWindowsFirst, (winmenuwins[i] == frontwin));
  1760.             }
  1761.         } else {
  1762.             /* We're not even in a game yet, turn entire menu off. */
  1763.             DisableItem(menu, 0);
  1764.         }
  1765.     }
  1766.     /* If a map window is frontmost, install and adjust the map view menu. */
  1767.     if (frontmap != NULL) {
  1768.         /* Delete the list view menu if that's what's installed currently. */
  1769.         menu = GetMHandle(mViewList);
  1770.         if (menu != nil)
  1771.           DeleteMenu(mViewList);
  1772.         /* Make sure the map view menu is installed (is always at the end). */
  1773.         InsertMenu(mapviewmenu, 0);
  1774.         menu = GetMHandle(mViewMap);
  1775.         if (menu != nil) {
  1776.             EnableItem(menu, 0);
  1777.             if (frontmap->vp->power == 0) {
  1778.                 DisableItem(menu, miViewFarther);
  1779.             } else {
  1780.                 EnableItem(menu, miViewFarther);
  1781.             }
  1782.             if (frontmap->vp->power == NUMPOWERS-1) {
  1783.                 DisableItem(menu, miViewCloser);
  1784.             } else {
  1785.                 EnableItem(menu, miViewCloser);
  1786.             }
  1787.             EnableItem(menu, miViewGrid);
  1788.             CheckItem(menu, miViewGrid, frontmap->drawgrid);
  1789.             EnableItem(menu, miViewTopline);
  1790.             CheckItem(menu, miViewTopline, (frontmap->toplineh > 0));
  1791.             EnableItem(menu, miViewTopunit);
  1792.             CheckItem(menu, miViewTopunit, (frontmap->topunith > 0));
  1793.             EnableItem(menu, miViewNames);
  1794.             CheckItem(menu, miViewNames, frontmap->drawnames);
  1795.             if (people_sides_defined()) {
  1796.                 EnableItem(menu, miViewPeople);
  1797.                 CheckItem(menu, miViewPeople, frontmap->drawpeople);
  1798.             } else {
  1799.                 DisableItem(menu, miViewPeople);
  1800.             }
  1801.             if (elevations_defined()) {
  1802.                 EnableItem(menu, miViewElevations);
  1803.                 CheckItem(menu, miViewElevations, frontmap->drawelevations);
  1804.             } else {
  1805.                 DisableItem(menu, miViewElevations);
  1806.             }
  1807.             if (temperatures_defined() || winds_defined() || clouds_defined()) {
  1808.                 EnableItem(menu, miViewWeather);
  1809.             } else {
  1810.                 DisableItem(menu, miViewWeather);
  1811.             }
  1812.             if (nummtypes > 0) {
  1813.                 EnableItem(menu, miViewMaterials);
  1814.                 /* (should do checkmark if anything in submenu is on) */
  1815.             } else {
  1816.                 DisableItem(menu, miViewMaterials);
  1817.             }
  1818.             if (numbordtypes + numconntypes + numcoattypes > 0) {
  1819.                 EnableItem(menu, miViewTerrain);
  1820.             } else {
  1821.                 DisableItem(menu, miViewTerrain);
  1822.             }
  1823.             if (world.daylength != 1) {
  1824.                 EnableItem(menu, miViewDaylight);
  1825.                 CheckItem(menu, miViewDaylight, frontmap->drawlighting);
  1826.             } else {
  1827.                 DisableItem(menu, miViewDaylight);
  1828.             }
  1829.             if (dside->coverage) {
  1830.                 EnableItem(menu, miViewCoverage);
  1831.                 CheckItem(menu, miViewCoverage, frontmap->drawcover);
  1832.             } else {
  1833.                 DisableItem(menu, miViewCoverage);
  1834.             }
  1835.             if (nummaps > 1) {
  1836.                 EnableItem(menu, miViewOtherMaps);
  1837.                 CheckItem(menu, miViewOtherMaps, frontmap->drawothermaps);
  1838.             } else {
  1839.                 DisableItem(menu, miViewOtherMaps);
  1840.             }
  1841.             menu = GetMHandle(mViewWeather);
  1842.             if (menu != nil) {
  1843.                 EnableItem(menu, 0);
  1844.                 if (temperatures_defined()) {
  1845.                     EnableItem(menu, miWeatherTemperature);
  1846.                     CheckItem(menu, miWeatherTemperature, frontmap->drawtemperature);
  1847.                 } else {
  1848.                     DisableItem(menu, miWeatherTemperature);
  1849.                 }
  1850.                 if (winds_defined()) {
  1851.                     EnableItem(menu, miWeatherWinds);
  1852.                     CheckItem(menu, miWeatherWinds, frontmap->drawwinds);
  1853.                 } else {
  1854.                     DisableItem(menu, miWeatherWinds);
  1855.                 }
  1856.                 if (clouds_defined()) {
  1857.                     EnableItem(menu, miWeatherClouds);
  1858.                     CheckItem(menu, miWeatherClouds, frontmap->drawclouds);
  1859.                 } else {
  1860.                     DisableItem(menu, miWeatherClouds);
  1861.                 }
  1862.                 /* should define what this means */
  1863.                 DisableItem(menu, miWeatherStorms);
  1864. /*                CheckItem(menu, miWeatherStorms, frontmap->drawstorms); */
  1865.             }
  1866.         }
  1867.     } else if (frontlist != NULL) {
  1868.         /* Do the list view menu similarly. */
  1869.         menu = GetMHandle(mViewMap);
  1870.         if (menu != nil)
  1871.           DeleteMenu(mViewMap);
  1872.         /* Make sure the menu is actually installed (is always at the end). */
  1873.         InsertMenu(listviewmenu, 0);
  1874.         menu = GetMHandle(mViewList);
  1875.         if (menu != nil) {
  1876.             EnableItem(menu, 0);
  1877.             if (1 /* at least one unit in list */) {
  1878.                 EnableItem(menu, miViewByType);
  1879.                 CheckItem(menu, miViewByType, (frontlist->mainsortmi == miViewByType));
  1880.                 EnableItem(menu, miViewByName);
  1881.                 CheckItem(menu, miViewByName, (frontlist->mainsortmi == miViewByName));
  1882.                 EnableItem(menu, miViewBySide);
  1883.                 CheckItem(menu, miViewBySide, (frontlist->mainsortmi == miViewBySide));
  1884.                 EnableItem(menu, miViewByActOrder);
  1885.                 CheckItem(menu, miViewByActOrder, (frontlist->mainsortmi == miViewByActOrder));
  1886.                 EnableItem(menu, miViewByLocation);
  1887.                 CheckItem(menu, miViewByLocation, (frontlist->mainsortmi == miViewByLocation));
  1888.                 /* should mark the secondary sort? */
  1889.                 EnableItem(menu, miViewWithTransport);
  1890.                 DisableItem(menu, miViewWithCommander);
  1891.                 EnableItem(menu, miViewIconSize);
  1892.                 CheckItem(menu, miViewIconSize, frontlist->largeicons);
  1893.             } else {
  1894.                 DisableItem(menu, miViewByType);
  1895.                 DisableItem(menu, miViewByName);
  1896.                 DisableItem(menu, miViewBySide);
  1897.                 DisableItem(menu, miViewByActOrder);
  1898.                 DisableItem(menu, miViewByLocation);
  1899.                 DisableItem(menu, miViewWithTransport);
  1900.                 DisableItem(menu, miViewWithCommander);
  1901.                 DisableItem(menu, miViewIconSize);
  1902.             }
  1903.         }
  1904.     } else {
  1905.         /* For any other window, disable any or all of the view menus, as needed. */
  1906.         menu = GetMHandle(mViewList);
  1907.         if (menu != nil)
  1908.           DisableItem(menu, 0);
  1909.         menu = GetMHandle(mViewMap);
  1910.         if (menu != nil)
  1911.           DisableItem(menu, 0);
  1912.     }
  1913.     menu = GetMHandle(mMagnifications);
  1914.     if (menu != nil) {
  1915.         /* Always on. */
  1916.         EnableItem(menu, 0);
  1917.         if (frontmap != NULL) {
  1918.             for (i = 0; i < NUMPOWERS; ++i) {
  1919.                 CheckItem(menu, i + 1, (i == frontmap->vp->power));
  1920.             }
  1921.         }
  1922.     }
  1923.     menu = GetMHandle(mMaterialTypes);
  1924.     if (menu != nil) {
  1925.         /* Always on, if any material types defined. */
  1926.         if (nummtypes > 0) {
  1927.             EnableItem(menu, 0);
  1928.             if (frontmap != NULL) {
  1929.                 for_all_material_types(m) {
  1930.                     if (any_cell_materials_defined() && cell_material_defined(m)) {
  1931.                         EnableItem(menu, m + 1);
  1932.                         CheckItem(menu, m + 1, frontmap->drawmaterials[m]);
  1933.                     } else {
  1934.                         CheckItem(menu, i, FALSE);
  1935.                         DisableItem(menu, m + 1);
  1936.                     }
  1937.                 }
  1938.             }
  1939.         } else {
  1940.             DisableItem(menu, 0);
  1941.         }
  1942.     }
  1943.     menu = GetMHandle(mOptTerrainTypes);
  1944.     if (menu != nil) {
  1945.         if (any_aux_terrain_defined()) {
  1946.             EnableItem(menu, 0);
  1947.             if (frontmap != NULL) {
  1948.                 numitems = CountMItems(menu);
  1949.                 for (i = 1; i <= numitems; ++i) {
  1950.                     t = frontmap->auxterraintypes[i];
  1951.                     if (any_aux_terrain_defined() && aux_terrain_defined(t)) {
  1952.                         EnableItem(menu, i);
  1953.                         CheckItem(menu, i, frontmap->drawauxterrain[t]);
  1954.                     } else {
  1955.                         CheckItem(menu, i, FALSE);
  1956.                         DisableItem(menu, i);
  1957.                     }
  1958.                 }
  1959.             }
  1960.         } else {
  1961.             DisableItem(menu, 0);
  1962.         }
  1963.     }
  1964.     menu = GetMHandle(mAITypes);
  1965.     if (menu != nil) {
  1966.         /* Always on. */
  1967.         EnableItem(menu, 0);
  1968.         CheckItem(menu, 1, (!side_has_ai(dside)));
  1969.         CheckItem(menu, 2, (side_has_ai(dside)));
  1970.     }
  1971.     /* Everything has been tweaked, redraw the menu bar. */
  1972.     DrawMenuBar();
  1973. }
  1974.  
  1975. /* Tweak the command menu according to what the unit can do. */
  1976. /* (some of these should have the menu text tweaked also, terms weird sometimes) */
  1977.  
  1978. static void
  1979. enable_commands_for_unit(MenuHandle menu, Unit *unit)
  1980. {
  1981.     int u = unit->type;
  1982.  
  1983.     /* If we can select the unit at all, we can always get a closeup of it. */
  1984.     EnableItem(menu, miPlayCloseup);
  1985.     /* (how to do checkmarks if multiple units selected? use '-' as per HIG) */
  1986.     CheckItem(menu, miPlayCloseup, (find_unit_closeup(unit) != NULL));
  1987.     /* If we don't actually have any control over the unit, or the game is over,
  1988.        nothing more to do. */
  1989.     if (!side_controls_unit(dside, unit) || endofgame)
  1990.       return;
  1991.     if (can_move_at_all(unit)) {
  1992.         EnableItem(menu, miPlayMove);
  1993.         /* also check for places to return to? */
  1994.         EnableItem(menu, miPlayReturn);
  1995.     }
  1996.     if (unit->plan) {
  1997.         EnableItem(menu, miPlaySetFormation);
  1998.         EnableItem(menu, miPlayWake);
  1999.         CheckItem(menu, miPlayWake, !unit->plan->asleep);
  2000.         EnableItem(menu, miPlaySleep);
  2001.         CheckItem(menu, miPlaySleep, unit->plan->asleep);
  2002.         EnableItem(menu, miPlayReserve);
  2003.         CheckItem(menu, miPlayReserve, unit->plan->reserve);
  2004.         EnableItem(menu, miPlayDelay);
  2005.         CheckItem(menu, miPlayDelay, unit->plan->delayed);
  2006.     }
  2007.     if (can_create(unit) || can_complete(unit) || can_research(unit)) {
  2008.         EnableItem(menu, miPlayBuild);
  2009.     }
  2010.     if (can_repair(unit)) {
  2011.         EnableItem(menu, miPlayRepair);
  2012.     }
  2013.     if (can_attack(unit)) {
  2014.         EnableItem(menu, miPlayAttack);
  2015.         EnableItem(menu, miPlayOverrun);
  2016.     }
  2017.     if (can_fire(unit)) {
  2018.         EnableItem(menu, miPlayFire);
  2019.         EnableItem(menu, miPlayFireInto);
  2020.     }
  2021.     if (can_detonate(unit)) {
  2022.         EnableItem(menu, miPlayDetonate);
  2023.     }
  2024.     if (1 /*dside->designer*/) {
  2025.         EnableItem(menu, miPlayGive);
  2026.     }
  2027.     if (side_can_disband(dside, unit)) {
  2028.         EnableItem(menu, miPlayDisband);
  2029.     }
  2030. #if 0
  2031.     /* change-type menu item not yet defined */ 
  2032.     if (can_change_type(unit)) {
  2033.         EnableItem(menu, miPlayChangeType);
  2034.     }
  2035. #endif
  2036.     if (can_add_terrain(unit)) {
  2037.         EnableItem(menu, miPlayAddTerrain);
  2038.     }
  2039.     if (can_remove_terrain(unit)) {
  2040.         EnableItem(menu, miPlayRemoveTerrain);
  2041.     }
  2042.     if (1 /* !unitnameslocked */) {
  2043.         EnableItem(menu, miPlayRename);
  2044.     }
  2045. }
  2046.